﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using middleware.utiles;
using System.IO;
using System.Reflection;
using System.Threading;
using middleware.dominio.persistencia;
using middleware.dominio.persistencia.exception;
using middleware.dominio.negocio.exception;


namespace middleware.dominio.negocio
{
    public sealed class Middleware : IMiddleware
    {
        private static readonly Middleware instance = new Middleware();
        private string[] comparaciones = { "=", "<", ">", "<=", ">=", "<>" };        
        public List<ITipoBandejaEntrada> tiposBandejasEntrada;
        public List<ITipoBandejaSalida> tiposBandejasSalida;
        public List<IConsulta> consultasDinamicas;
        public List<BandejaEntrada> bandejasEntrada;
        public List<BandejaSalida> bandejasSalida;
        public List<Regla> reglas;
        public Usuario usuarioLogueado;
        public ParametroSistema parametraSistema;
        public bool corriendo;

        // variable para controlar detencion del thread de procesamiento de mensajes.
        private volatile Boolean pedidoDetencion = false;

        private Thread procesamientoThread = null;

        private LogManager logger = LogManager.getInstance();

        private IMiddlewarePersistencia middlewarePersistencia = PersistenceFactory.getMiddlewarePersistencia();

        private ConsultasManager consultasManager = ConsultasManager.getInstance();

        private volatile int tiempoPeriodicidad = 0;

        public static string CREACION_BANDEJA_ENTRADA = "Creacion de la Bandeja de Entrada: ";

        public static string CREACION_BANDEJA_SALIDA = "Creacion de la Bandeja de Salida: ";

        public static string CREACION_REGLA = "Creacion de la Regla: ";

        public static string INICIO_EJECUCION = "Inicio de la Ejecucion";

        public static string DETENCION_EJECUCION = "Detencion de la Ejecucion";

        public static string ERROR_EJECUCION = "Error en la Ejecucion ";

        private Middleware()
        {
            this.tiposBandejasEntrada = new List<ITipoBandejaEntrada>();
            this.tiposBandejasSalida = new List<ITipoBandejaSalida>();
            this.consultasDinamicas = new List<IConsulta>();
            this.bandejasEntrada = new List<BandejaEntrada>();
            this.bandejasSalida = new List<BandejaSalida>();
            this.reglas = new List<Regla>();
            this.usuarioLogueado = null;
            this.parametraSistema = null;
            corriendo = false;
        }

        public static Middleware getInstance()
        {
            return instance;
        }

        //Usuario
        public Usuario usuarioCorrecto(string usuario, string contrasena)
        {
            Usuario result = null;

            try 
            {
                result = this.middlewarePersistencia.ObtenerUsuarioPersistido(usuario, contrasena);
            }
            catch (ConsultarPersisteciaException e) 
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "durante el logueo del Usuario", e);
            }            

            if (result != null)
            {                
                this.usuarioLogueado = result;
            }
            return result;
        }

        public void SetUsuarioLogueado(Usuario usuario)
        {
            this.usuarioLogueado = usuario;            
        }

        public Usuario GetUsuarioLogueado()
        {
            return this.usuarioLogueado;
        }

        public void cargarComponentes(string directorioRaiz)
        {
            try
            {
                //Cargo los componentes de bandejas de Entrada
                ITipoBandejaEntrada tipoBandejaEntrada;
                if (directorioRaiz != null && directorioRaiz.CompareTo("") != 0)
                {
                    string directorioEntrada = directorioRaiz + @"\entrada\";
                    if (Directory.Exists(directorioEntrada))
                    {
                        string[] listaDlls = Directory.GetFiles(directorioEntrada, "*.dll", SearchOption.TopDirectoryOnly);
                        if (listaDlls != null)
                        {
                            for (int i = 0; i < listaDlls.Length; i++)
                            {
                                Assembly assembly = Assembly.LoadFile(listaDlls[i]);

                                //Recorro para ver los tipos que puedo instanciar
                                foreach (Type tipo in assembly.GetTypes())
                                {
                                    if (tipo.Name.Contains(@"BandejaEntrada")) //Para asegurarnos de instanciar solo las entradas
                                    {
                                        //Creo la instancia del tipo de bandeja y lo agrego a la lista
                                        tipoBandejaEntrada = (ITipoBandejaEntrada)Activator.CreateInstance(tipo);
                                        this.ObtenerTiposBandejasEntrada().Add(tipoBandejaEntrada);
                                    }
                                }
                            }
                        }
                    }
                }
                //Cargo los componentes de bandejas de Entrada
                ITipoBandejaSalida tipoBandejaSalida;
                if (directorioRaiz != null && directorioRaiz.CompareTo("") != 0)
                {
                    string directorioSalida = directorioRaiz + @"\salida\";
                    if (Directory.Exists(directorioSalida))
                    {
                        string[] listaDlls = Directory.GetFiles(directorioSalida, "*.dll", SearchOption.TopDirectoryOnly);
                        if (listaDlls != null)
                        {
                            for (int i = 0; i < listaDlls.Length; i++)
                            {
                                Assembly assembly = Assembly.LoadFile(listaDlls[i]);

                                //Recorro para ver los tipos que puedo instanciar
                                foreach (Type tipo in assembly.GetTypes())
                                {
                                    if (tipo.Name.Contains(@"BandejaSalida"))
                                    {
                                        //Creo la instancia del tipo de bandeja y lo agrego a la lista
                                        tipoBandejaSalida = (ITipoBandejaSalida)Activator.CreateInstance(tipo);
                                        this.ObtenerTiposBandejasSalida().Add(tipoBandejaSalida);
                                    }
                                }
                            }
                        }
                    }
                }
                // Cargo Consultas dinamicas
                this.ObtenerConsultasDinamicas().AddRange(consultasManager.CargarConsultas(directorioRaiz + @"\consulta\"));
            }
            catch (BusinessException e)
            {
                this.logger.CrearLog(this.usuarioCorrecto("system", "system"), e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se cargaban los componentes", e);
            }
        }

        public List<ITipoBandejaEntrada> ObtenerTiposBandejasEntrada()
        {
            return tiposBandejasEntrada;
        }

        public List<ITipoBandejaSalida> ObtenerTiposBandejasSalida() 
        {
            return tiposBandejasSalida;
        }

        public List<IConsulta> ObtenerConsultasDinamicas()
        {
            return this.consultasDinamicas;
        }

        public List<BandejaEntrada> ObtenerBandejasEntrada() 
        {
            //Actualizo la lista de bandejas de entrada
            try
            {
                this.bandejasEntrada = this.middlewarePersistencia.ObtenerPersistenciaBandejasEntrada();

                foreach (BandejaEntrada bandeja in this.bandejasEntrada)
                {
                    bandeja.tipoBandeja = this.ObtenerTipoBandejaEntrada(this.tiposBandejasEntrada, bandeja);
                }
            }
            catch (ConsultarPersisteciaException e)
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se consultaban las bandejas de entrada", e);
            }
            catch (BusinessException e) 
            {
                throw new BusinessException(ERROR_EJECUCION + "mientras se consultaban los tipos de bandejas de entrada", e);
            }
            return this.bandejasEntrada;
        }

        public List<BandejaSalida> ObtenerBandejasSalida() 
        {
            try
            {
                this.bandejasSalida = this.middlewarePersistencia.ObtenerPersistenciaBandejasSalida();
                foreach (BandejaSalida bandeja in this.bandejasSalida)
                {
                    bandeja.tipoBandeja = this.ObtenerTipoBandejaSalida(this.tiposBandejasSalida, bandeja);
                }
            }
            catch (ConsultarPersisteciaException e)
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se consultaban las bandejas de salida", e);
            }
            catch (BusinessException e)
            {
                throw new BusinessException(ERROR_EJECUCION + "mientras se consultaban los tipos de bandejas de salida", e);
            }
            return this.bandejasSalida;
        }

        public List<Regla> ObtenerReglas()
        {
            try
            {
                this.reglas = this.middlewarePersistencia.ObtenerPersistenciaReglas();
            }
            catch (ConsultarPersisteciaException e)
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se consultaban las reglas", e);
            }
            return this.reglas;
        }

        public BandejaEntrada CrearBandejaEntrada(ITipoBandejaEntrada tipoBandejaEntrada, string nombre, string configuracion)
        {   
            BandejaEntrada bandejaEntrada = null;
            try
            {
                if (this.ValidarBandeja(nombre, configuracion, true))
                {
                    bandejaEntrada = new BandejaEntrada();
                    bandejaEntrada.nombre = nombre;
                    bandejaEntrada.configuracion = configuracion;
                    bandejaEntrada.tipoBandeja = tipoBandejaEntrada;
                    bandejaEntrada.tipoBandeja.setConfiguracion(bandejaEntrada.configuracion);
                    bandejaEntrada.nombreTipoBandeja = tipoBandejaEntrada.ToString();
                    bandejaEntrada = this.middlewarePersistencia.PersistirBandejaEntrada(bandejaEntrada);
                    if (bandejaEntrada != null)
                    {
                        this.logger.CrearLog(this.usuarioLogueado, CREACION_BANDEJA_ENTRADA + bandejaEntrada.BandejaID);
                    }
                }
            }
            catch (AgregarPersisteciaException e)
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se guardaba la bandeja de entrada", e);
            }
            return bandejaEntrada;
        }

        public BandejaSalida CrearBandejaSalida(ITipoBandejaSalida tipoBandejaSalida, string nombre, string configuracion)
        {
            BandejaSalida bandejaSalida = null;
            try
            {
                if (this.ValidarBandeja(nombre, configuracion, false))
                {
                    bandejaSalida = new BandejaSalida();
                    bandejaSalida.nombre = nombre;
                    bandejaSalida.configuracion = configuracion;
                    bandejaSalida.tipoBandeja = tipoBandejaSalida;
                    bandejaSalida.tipoBandeja.setConfiguracion(bandejaSalida.configuracion);
                    bandejaSalida.nombreTipoBandeja = tipoBandejaSalida.ToString();
                    bandejaSalida = this.middlewarePersistencia.PersistirBandejaSalida(bandejaSalida);
                    if (bandejaSalida != null)
                    {
                        this.logger.CrearLog(this.usuarioLogueado, CREACION_BANDEJA_SALIDA + bandejaSalida.BandejaId);
                    }
                }
            }
            catch (AgregarPersisteciaException e)
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se guardaba la bandeja de salida", e);
            }
            return bandejaSalida;
        }

        private Boolean ValidarBandeja(string nombre, string configuracion, Boolean entrada)
        {
            Boolean result = true;
            try
            {
                if (String.IsNullOrEmpty(nombre) || String.IsNullOrEmpty(configuracion))
                {
                    result = false;
                }
                if (result)
                {
                    if (entrada)
                    {
                        if (this.ObtenerBandejaEntrada(this.ObtenerBandejasEntrada(), nombre) != null)
                        {
                            result = false;
                        }
                    }
                    else
                    {
                        if (this.ObtenerBandejaSalida(this.ObtenerBandejasSalida(), nombre) != null)
                        {
                            result = false;
                        }
                    }
                }
            }
            catch (BusinessException e)
            {
                throw new BusinessException(ERROR_EJECUCION + "mientras se validaba la bandeja " + nombre, e);
            }
            return result;
        }

        public Regla CrearRegla(string nombreAtributo, string condicion, string valorAtributo, BandejaSalida bandeja)
        {
            Regla regla = new Regla();

            try
            {
                if (this.ValidarRegla(nombreAtributo, condicion, valorAtributo))
                {
                    regla.nombreAtributo = nombreAtributo;
                    regla.codicion = condicion;
                    regla.valorAtributo = valorAtributo;
                    regla.bandeja = bandeja;
                    regla = this.middlewarePersistencia.PersistirRegla(regla);
                    if (regla != null)
                    {
                        this.logger.CrearLog(this.usuarioLogueado, CREACION_REGLA + regla.ReglaId);
                    }
                }
                else
                {
                    regla = null;
                }
            }
            catch (AgregarPersisteciaException e)
            {
                throw new BusinessException(ERROR_EJECUCION + "mientras se guardaba la regla", e);
            }
            return regla;
        }

        private Boolean ValidarRegla(string nombreAtributo, string condicion, string valorAtributo)
        {
            Boolean result = true;

            try
            {
                if (String.IsNullOrEmpty(nombreAtributo) || String.IsNullOrEmpty(condicion) || String.IsNullOrEmpty(valorAtributo))
                {
                    result = false;
                }

                if (result)
                {
                    result = ValidarCondicion(condicion);
                }
            }
            catch (BusinessException e)
            {
                throw new BusinessException(ERROR_EJECUCION + "mientras se validaba la regla", e);
            }

            return result;
        }

        private Boolean ValidarCondicion(string condicion)
        {
            Boolean result = false;            
            for (int i = 0; i < this.comparaciones.Length; i++)
            {
                if (condicion.CompareTo(this.comparaciones[i]) == 0)
                {
                    result = true;
                    break;
                }
            }            

            return result;
        }

        public void ComenzarProcesamiento()
        {
            try
            {
                corriendo = true;
                pedidoDetencion = false;
                procesamientoThread = new Thread(this.ProcesarMensajes);

                procesamientoThread.Start();
                while (!procesamientoThread.IsAlive) ;
            }
            catch (BusinessException e)
            {
                throw new BusinessException(ERROR_EJECUCION + "mientras procesaban los mensajes", e);
            }
        }

        public void DetenerProcesamiento()
        {
            try
            {
                corriendo = false;
                pedidoDetencion = true;
                procesamientoThread.Join();
            }
            catch (BusinessException e)
            {
                throw new BusinessException(ERROR_EJECUCION + "mientras se detenia el procesamiento de mensajes", e);
            }
        }

        private void ProcesarMensajes()
        {
            this.logger.CrearLog(this.usuarioLogueado, INICIO_EJECUCION);
            try
            {
                while (!pedidoDetencion)
                {
                    // Recorro las Bandejas de Entrada y Comienzo a procesas los mensajes            
                    foreach (BandejaEntrada bandejaEntrada in this.ObtenerBandejasEntrada())
                    {
                        Mensaje mensaje = null;
                        bandejaEntrada.tipoBandeja.setConfiguracion(bandejaEntrada.configuracion);
                        while (!pedidoDetencion && bandejaEntrada.tipoBandeja.ElementosSinLeer() > 0)
                        {
                            mensaje = bandejaEntrada.tipoBandeja.ObtenerMensaje();
                            bandejaEntrada.tipoBandeja.MarcarComoLeido(mensaje);
                            mensaje = this.middlewarePersistencia.PersistirMensaje(mensaje);
                            List<BandejaSalida> bandejasSalidaMensaje = this.ObtenerBandejasParaMensaje(mensaje);
                            foreach (BandejaSalida bandejaSalida in bandejasSalidaMensaje)
                            {
                                bandejaSalida.tipoBandeja = this.ObtenerTipoBandejaSalida(this.tiposBandejasSalida, bandejaSalida);
                                bandejaSalida.tipoBandeja.setConfiguracion(bandejaSalida.configuracion);
                                bandejaSalida.tipoBandeja.EscribirMensaje(mensaje);
                                this.CrearHistorico(mensaje, bandejaEntrada, bandejaSalida, this.ObtenerReglaBandejaSalida(bandejaSalida, mensaje));
                                if (pedidoDetencion)
                                {
                                    break;
                                }
                            }
                        }
                        if (pedidoDetencion)
                        {
                            break;
                        }

                    }
                    if (!pedidoDetencion)
                    {
                        Thread.Sleep(tiempoPeriodicidad * 1000);
                    }
                }
            }
            catch (AgregarPersisteciaException e)
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se guardaban los mensajes", e);
            }
            catch (BusinessException e)
            {
                throw new BusinessException(ERROR_EJECUCION + "mientras se procesaban los mensajes", e);
            }
            this.logger.CrearLog(this.usuarioLogueado, DETENCION_EJECUCION);
        }

        /**
         * Metodo que encuentra el listado de bandejas de salida por las cuales un mensaje puede ser enviado
         */
        private List<BandejaSalida> ObtenerBandejasParaMensaje(Mensaje mensaje)
        {
            List<BandejaSalida> listaResult = new List<BandejaSalida>();

            try
            {
                foreach (Regla regla in this.ObtenerReglas())
                {
                    if (regla.MensajeCumpleRegla(mensaje) && !this.DentroDeListaSalida(listaResult, regla.bandeja.nombre))
                    {
                        listaResult.Add(regla.bandeja);
                    }
                }
            }
            catch (BusinessException e)
            {
                throw new BusinessException(ERROR_EJECUCION + "mientras buscaban las bandejas de un mensaje", e);
            }
            return listaResult;
        }

        private Boolean DentroDeListaSalida(List<BandejaSalida> lista, string nombreBandeja)       
        {
            Boolean result = false;
            try
            {
                foreach (BandejaSalida bandejaSalida in lista)
                {
                    if (bandejaSalida.nombre.CompareTo(nombreBandeja) == 0)
                    {
                        result = true;
                        break;
                    }
                }
            }
            catch (BusinessException e)
            {
                throw new BusinessException(ERROR_EJECUCION + "mientras se validaba que una bandeja de salida estaba en un listado", e);
            }

            return result;
        }

        /**
         * Metodo que encuentra la regla en la que aplico un mensaje para una bandeja de salida
         */
        private Regla ObtenerReglaBandejaSalida(BandejaSalida bandejaSalida, Mensaje mensaje)
        {
            Regla regla = null;
            try
            {
                foreach (Regla r in this.ObtenerReglas())
                {
                    if (r.MensajeCumpleRegla(mensaje) && r.bandeja.BandejaId == bandejaSalida.BandejaId)
                    {
                        regla = r;
                        break;
                    }
                }
            }
            catch (BusinessException e)
            {
                throw new BusinessException(ERROR_EJECUCION + "mientras se buscaba la regla en la que aplico un mensaje", e);
            }
            return regla;
        }

        public void ModificarTiempoLectura(int valor)
        {
            try
            {
                this.parametraSistema = middlewarePersistencia.PersistirParametroSistema(this.parametraSistema, valor);
                this.tiempoPeriodicidad = valor;
            }
            catch (AgregarPersisteciaException e)
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se modificaba el tiempo de lectura", e);
            }
        }

        public int ObtenerTiempoLectura()
        {
            try
            {
                this.parametraSistema = middlewarePersistencia.ObtenerParametroSistema();
                this.tiempoPeriodicidad = this.parametraSistema.tiempoLectura;
            }
            catch (ConsultarPersisteciaException e)
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se obtenia el tiempo de lectura", e);
            }
            return this.tiempoPeriodicidad;
        }

        public Boolean ModificarBandejaEntrada(BandejaEntrada bandejaEntrada, ITipoBandejaEntrada tipoBandejaEntrada, string nombre, string configuracion)
        {
            Boolean result = true;
            try
            {
                if (!String.IsNullOrEmpty(nombre) && bandejaEntrada.nombre.CompareTo(nombre) != 0 && this.ObtenerBandejaEntrada(this.ObtenerBandejasEntrada(), nombre) != null)
                {
                    result = false;
                }

                if (result && (!String.IsNullOrEmpty(nombre) || !String.IsNullOrEmpty(configuracion) || tipoBandejaEntrada != null))
                {
                    result = middlewarePersistencia.ModificarBandejaEntradaPersistida(bandejaEntrada, tipoBandejaEntrada, nombre, configuracion);
                }
            }
            catch (ModificarPersistenciaException e)
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se modificaba la bandeja de entrada", e);
            }
            return result;            
        }

        public Boolean ModificarBandejaSalida(BandejaSalida bandejaSalida, ITipoBandejaSalida tipoBandejaSalida, string nombre, string configuracion)
        {
            Boolean result = true;
            try
            {
                if (!String.IsNullOrEmpty(nombre) && bandejaSalida.nombre.CompareTo(nombre) != 0 && this.ObtenerBandejaSalida(this.ObtenerBandejasSalida(), nombre) != null)
                {
                    result = false;
                }

                if (result && (!String.IsNullOrEmpty(nombre) || !String.IsNullOrEmpty(configuracion) || tipoBandejaSalida != null))
                {
                    result = middlewarePersistencia.ModificarBandejaSalidaPersistida(bandejaSalida, tipoBandejaSalida, nombre, configuracion);
                }
            }
            catch (ModificarPersistenciaException e)
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se modificaba la bandeja de salida", e);
            }

            return result;
        }

        private BandejaEntrada ObtenerBandejaEntrada(List<BandejaEntrada> lista, string nombre)
        {
            BandejaEntrada result = null;
            result = PersistenceFactory.getMiddlewarePersistencia().ObtenerBandejaEntradaPersistida(nombre);
            if (result != null) result.tipoBandeja = this.ObtenerTipoBandejaEntrada(this.tiposBandejasEntrada, result);
            return result;
        }

        private BandejaSalida ObtenerBandejaSalida(List<BandejaSalida> lista, string nombre)
        {
            BandejaSalida result = null;
            result = PersistenceFactory.getMiddlewarePersistencia().ObtenerBandejaSalidaPersistida(nombre);
            if (result != null) result.tipoBandeja = this.ObtenerTipoBandejaSalida(this.tiposBandejasSalida, result);
            return result;
        }

        public Boolean ModificarRegla(Regla regla, string nombreAtributo, string condicion, string valorAtributo, BandejaSalida bandejaSalida)
        {
            Boolean result = true;
            try
            {
                if (!String.IsNullOrEmpty(condicion) && !this.ValidarCondicion(condicion))
                {
                    result = false;
                }
                else
                {
                    result = middlewarePersistencia.ModificarReglaPersistida(regla, nombreAtributo, condicion, valorAtributo, bandejaSalida);
                }
            }
            catch (ModificarPersistenciaException e)
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se modificaba la regla", e);
            }
            return result;
        }

        public Boolean EliminarBandejaEntrada(BandejaEntrada bandejaEntrada)
        {
            Boolean aRetornar = false;
            aRetornar = middlewarePersistencia.EliminarBandejaEntrada(bandejaEntrada);
            return aRetornar;
        }

        public Boolean EliminarBandejaSalida(BandejaSalida bandejaSalida)
        {
            Boolean aRetornar = false;
            aRetornar = PersistenceFactory.getMiddlewarePersistencia().EliminarBandejaSalida(bandejaSalida);
            return aRetornar;
        }


        public Boolean EliminarRegla(Regla regla)
        {
            Boolean aRetornar = false;
            aRetornar = PersistenceFactory.getMiddlewarePersistencia().EliminarRegla(regla);
            return aRetornar;
        }

        private Historico CrearHistorico(Mensaje mensaje ,BandejaEntrada bandejaEntrada, BandejaSalida bandejaSalida, Regla regla)
        {
            Historico historico = new Historico();
            try
            {
                historico.fecha = DateTime.Now;
                historico.mensaje = mensaje;
                historico.bandejaEntrada = bandejaEntrada;
                historico.bandejaSalida = bandejaSalida;
                historico.regla = regla;
                this.middlewarePersistencia.PersistirHistorico(historico);
            }
            catch (AgregarPersisteciaException e)
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se guardaba el historico", e);
            }
            return historico;
        }

        public List<Historico> ObtenerHistoricos(DateTime fecha, BandejaEntrada bandejaEntrada, string nombreAtributo, string valorAtributo)
        {
            List<Historico> result = new List<Historico>();
            try
            {
                result = this.middlewarePersistencia.ObtenerHistoricoPersistido(fecha, bandejaEntrada, nombreAtributo, valorAtributo);
            }
            catch (ConsultarPersisteciaException e)
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se obtenian los historicos", e);
            }
            return result;
        }

        public List<Log> ObtenerLogs(DateTime fecha, string linea)
        {          
            return this.logger.ObtenerLogs(fecha,linea);
        }

        private ITipoBandejaEntrada ObtenerTipoBandejaEntrada(List<ITipoBandejaEntrada> lista, BandejaEntrada bandejaEntrada)
        {
            ITipoBandejaEntrada result = null;

            foreach (ITipoBandejaEntrada tipo in lista)
            {
                if (bandejaEntrada.nombreTipoBandeja.CompareTo(tipo.ToString()) == 0)
                {
                    result = tipo;
                    break;
                }
            }
            return result;
        }

        private ITipoBandejaSalida ObtenerTipoBandejaSalida(List<ITipoBandejaSalida> lista, BandejaSalida bandejaSalida)
        {
            ITipoBandejaSalida result = null;

            foreach (ITipoBandejaSalida tipo in lista)
            {
                if (bandejaSalida.nombreTipoBandeja.CompareTo(tipo.ToString()) == 0)
                {
                    result = tipo;
                    break;
                }
            }
            return result;
        }

        public bool ControlarExistaBaseDatos()
        {
            return this.middlewarePersistencia.CrearBaseDatosSiNoExiste();
        }

        public bool EstaCorriendoProceso()
        {
            return corriendo;
        }

        public List<string[]> RealizarConsultaDinamica(IConsulta consulta, string[] filtros)
        {
            List<String[]> resultado = new List<string[]>();
            try
            {
                consulta.AgregarFiltros(filtros);
                resultado = consultasManager.EjecutarConsulta(consulta);                
            }            
            catch (BusinessException e) 
            {
                this.logger.CrearLog(this.usuarioLogueado, e.ToString());
                throw new BusinessException(ERROR_EJECUCION + "mientras se realizaba la consulta dinamica", e);
            }

            return resultado;
        }

        public string[] ObtenerNombresFiltros(IConsulta consulta)
        {
            return consulta.ObtenerNombresFiltros();
        }

        public string[] ObtenerCabezalConsulta(IConsulta consulta)
        {
            return consulta.ObtenerCabezal();
        }
    }
}